from flask import Blueprint, current_app
from flask import request
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
import re
import json

from app.decisionTree.decisionTree import DecisionTreeTrainer
from app.models import db, Product
from app.models import User
import app.utils as utils
import app.utils.market as market
from app.ai_service import ai_service as ai
from app.decisionTree import decisionTree
from sklearn.tree import DecisionTreeClassifier

data_controller = Blueprint('data_controller', __name__)

# 统一为每个请求打印日志，通过“蓝图.before_request”和“蓝图.after_request”
@data_controller.before_request
def log_request_info():
    current_app.logger.info(f"收到请求: {request.method} {request.url}")
@data_controller.after_request
def log_response_info(response):
    current_app.logger.info(f"响应状态码: {response.status_code}")
    return response


@data_controller.post('/factor')
@jwt_required()
def factor_mining():

    user_id = get_jwt_identity()
    user = User.query.get(user_id)

    # 初始化deepseek模型
    model = ai.DeepSeekAI()

    #获取前端数据user_data，market_data，selected_stocks(holding products)用于训练model
    data = request.get_json()
    market_data = data['market_data']
    products = user.products
    product_list = [{
        "code": p.code,
        "name": p.name,
        "type": p.type,
        "industry": p.industry,
        "quantity": p.quantity,
        "cost_price": float(p.cost_price) if p.cost_price is not None else None,  # 处理 Decimal
        "latest_price": float(p.latest_price) if p.latest_price is not None else None,  # 处理 Decimal
        "buy_date": p.buy_date.isoformat() if p.buy_date is not None else None,  # 处理 datetime
        "note": p.note
    } for p in products]


    # 构建分析文本
    # 用户画像参数有待商榷
    analysis_text = f"""
    [用户画像]
    风险偏好: {user.risk_level}
    投资偏好: {user.preferred_investment}
    投资期限: {user.preferred_horizen}

    [持仓产品]
    {json.dumps(product_list, indent=2, ensure_ascii=False)}

    [市场数据]
    {json.dumps(market_data, indent=2, ensure_ascii=False)}
    """

    # 提取金融因子
    try:
        factors = model.financial_factors_mining(analysis_text)

        # 标准化返回格式
        if isinstance(factors, dict) and "error" in factors:
            return utils.error(message = "因子提取错误", code = 500)

        return utils.success(message = "因子提取成功", data = factors)

    except Exception as e:
        return utils.error(message = f"服务器错误: {str(e)}",code = 500)

@data_controller.post('/advice')
@jwt_required()
def advice():

    user_id = get_jwt_identity()
    user = User.query.get(user_id)
    model = ai.DeepSeekAI()

    # 获取前端数据
    data = request.get_json()
    factors = data['factors']
    market_data = data['market_data']
    products = user.products
    product_list = [{
        "code": p.code,
        "name": p.name,
        "type": p.type,
        "industry": p.industry,
        "quantity": p.quantity,
        "cost_price": float(p.cost_price) if p.cost_price is not None else None,  # 处理 Decimal
        "latest_price": float(p.latest_price) if p.latest_price is not None else None,  # 处理 Decimal
        "buy_date": p.buy_date.isoformat() if p.buy_date is not None else None,  # 处理 datetime
        "note": p.note
    } for p in products]

    trainer = DecisionTreeTrainer()
    trainer.train(user_id)

    funds, predicted_stocks = trainer.predict_market_data(market_data)

    predicted_stocks.append(market_data[0])

    # 构建分析文本
    analysis_text = f"""
        [用户画像]
        风险偏好: {user.risk_level}
        投资偏好: {user.preferred_investment}
        投资期限: {user.preferred_horizen}
        
        [影响因子]
        {json.dumps(factors, indent=2, ensure_ascii=False)}
        
        [持仓产品]
        {json.dumps(product_list, indent=2, ensure_ascii=False)}

        [市场基金数据]
        {json.dumps(funds, indent=2, ensure_ascii=False)}
        
        [市场股票数据]
        {json.dumps(predicted_stocks, indent=2, ensure_ascii=False)}
        """

    try:
        advice_ = model.advice_generator(analysis_text)
        # 标准化返回格式
        if isinstance(factors, dict) and "error" in advice_:
            return utils.error(message = "投资建议生成错误", code = 500)

        return utils.success(message = "投资建议生成成功", data = advice_)

    except Exception as e:
        return utils.error(message = f"服务器错误: {str(e)}",code = 500)

